﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using ThridLibray;

namespace Camera
{
    public class CameraDahua : CameraBase
    {
        private const int DEFAULT_INTERVAL = 40;

        /* 设备对象 */
        private IDevice m_dev;
        private readonly Stopwatch m_stopWatch;    /* 时间统计器 */
        private string key;
        private bool m_bDisConnect;

        public override event ReadImageDelegate ReadImageEvent;
        public override event ConnectLossDelegate ConnectLossEvent;

        public CameraDahua()
        {
            m_stopWatch = new Stopwatch();
            m_stopWatch.Start();
        }

        public static string[] DeviceListAcq()
        {
            /* 设备搜索 */
            List<IDeviceInfo> li = Enumerator.EnumerateDevices();
            string[] deviceList = new string[li.Count];
            for (int i = 0; i < li.Count; ++i)
            {
                deviceList[i] = li[i].Key;
            }
            return deviceList;
        }

        /* 判断是否应该做显示操作 */
        private bool IsTimeToDisplay()
        {
            m_stopWatch.Stop();
            long m_lDisplayInterval = m_stopWatch.ElapsedMilliseconds;
            if (m_lDisplayInterval <= DEFAULT_INTERVAL)
            {
                m_stopWatch.Start();
                return false;
            }
            else
            {
                m_stopWatch.Reset();
                m_stopWatch.Start();
                return true;
            }
        }

        /* 相机打开回调 */
        private void OnCameraOpen(object sender, EventArgs e)
        {

        }

        /* 相机关闭回调 */
        private void OnCameraClose(object sender, EventArgs e)
        {

        }

        /* 相机丢失回调 */
        private void OnConnectLoss(object sender, EventArgs e)
        {
            ConnectLossEvent("相机 " + key + " 异常掉线，重新连接中。。。");
            m_bDisConnect = false;
            try
            {
                m_dev.StreamGrabber.ImageGrabbed -= OnImageGrabbed;         /* 反注册回调 */
                m_dev.ShutdownGrab();                                       /* 停止码流 */
                m_dev.Close();                                              /* 关闭相机 */
            }
            catch (Exception)
            {

            }
            while (!m_bDisConnect)
            {
                try
                {
                    /* 获取搜索到的第一个设备 */
                    m_dev = Enumerator.GetDeviceByKey(key);
                    /* 注册链接时间 */
                    m_dev.CameraOpened += OnCameraOpen;
                    m_dev.ConnectionLost += OnConnectLoss;
                    m_dev.CameraClosed += OnCameraClose;
                    /* 打开设备 */
                    if (!m_dev.Open())
                    {
                        m_dev.Close();                                              /* 关闭相机 */
                        continue;
                    }
                    /* 注册码流回调事件 */
                    m_dev.StreamGrabber.ImageGrabbed += OnImageGrabbed;
                    /* 开启码流 */
                    if (!m_dev.GrabUsingGrabLoopThread())
                    {
                        m_dev.Close();                                              /* 关闭相机 */
                        continue;
                    }
                }
                catch (Exception)
                {
                    continue;
                }
                m_bDisConnect = true;
            }
        }

        /* 码流数据回调 */
        private void OnImageGrabbed(object sender, GrabbedEventArgs e)
        {
            /* 主动调用回收垃圾 */
            GC.Collect();
            /* 控制显示最高帧率为25FPS */
            if (!IsTimeToDisplay())
            {
                return;
            }
            //try
            //{
            // 转换为Halcon黑白图像显示
            //HOperatorSet.GenImage1(out HObject Hobj, "byte", e.GrabResult.Width, e.GrabResult.Height, e.GrabResult.Raw);
            Imgdata imgdata = new Imgdata
            {
                data = e.GrabResult.Raw,
                width = e.GrabResult.Width,
                height = e.GrabResult.Height
            };
            ReadImageEvent(imgdata);
            //}
            //catch (Exception)
            //{

            //}
        }

        public override bool Open(string key)
        {
            this.key = key;
            /* 设备搜索 */
            Enumerator.EnumerateDevices();
            try
            {
                /* 获取搜索到的第一个设备 */
                m_dev = Enumerator.GetDeviceByKey(key);
                /* 注册链接时间 */
                m_dev.CameraOpened += OnCameraOpen;
                m_dev.ConnectionLost += OnConnectLoss;
                m_dev.CameraClosed += OnCameraClose;
                /* 打开设备 */
                if (!m_dev.Open())
                {
                    return false;
                }
                /* 设置图像格式 */
                using (IEnumParameter p = m_dev.ParameterCollection[ParametrizeNameSet.ImagePixelFormat])
                {
                    p.SetValue("Mono8");
                }
                /* 设置缓存个数为8（默认值为16） */
                m_dev.StreamGrabber.SetBufferCount(8);
                /* 注册码流回调事件 */
                m_dev.StreamGrabber.ImageGrabbed += OnImageGrabbed;
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        public override bool Close()
        {
            if (m_dev == null)
            {
                return false;
            }
            try
            {
                m_dev.StreamGrabber.ImageGrabbed -= OnImageGrabbed;         /* 反注册回调 */
                m_dev.ShutdownGrab();                                       /* 停止码流 */
                m_dev.Close();                                              /* 关闭相机 */
            }
            catch (Exception)
            {
                return false;
            }
            m_dev.Dispose();
            m_dev = null;
            return true;
        }

        public override void SetTriggerSource(TriggerSource triggerSource)
        {
            if (m_dev == null)
            {
                return;
            }
            string source;
            switch (triggerSource)
            {
                case TriggerSource.Line1:
                    source = TriggerSourceEnum.Line1;
                    break;
                case TriggerSource.Software:
                    source = TriggerSourceEnum.Software;
                    break;
                default:
                    return;
            }
            /* 打开Trigger(Line1) */
            m_dev.TriggerSet.Open(source);
        }

        public override bool TriggerSoftware()
        {
            if (m_dev == null)
            {
                return false;
            }
            try
            {
                m_dev.ExecuteSoftwareTrigger();
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        public override string GetSerialNumber()
        {
            return key;
        }

        public override void SetTriggerMode(TriggerMode triggerMode)
        {
            if (m_dev == null)
            {
                return;
            }
            using (IEnumParameter p = m_dev.ParameterCollection[ParametrizeNameSet.TriggerMode])
            {
                p.SetValue(triggerMode.ToString());
            }
        }

        public override double GetParameter(string key)
        {
            if (m_dev == null)
            {
                return 0;
            }
            using (IFloatParameter p = m_dev.ParameterCollection[new FloatName(key)])
            {
                return p.GetValue();
            }
        }

        public override void SetParameter(string key, double fValue)
        {
            if (m_dev == null)
            {
                return;
            }
            using (IFloatParameter p = m_dev.ParameterCollection[new FloatName(key)])
            {
                p.SetValue(fValue);
            }
        }

        public override bool StartGrab()
        {
            /* 开启码流 */
            return m_dev != null && m_dev.GrabUsingGrabLoopThread();
        }

        public override void StopGrab()
        {
            m_dev?.ShutdownGrab();                                       /* 停止码流 */
        }

        public override void UserSave()
        {
            m_dev?.UserSet.Save(UserSetType.userSet1);
        }

        public override void LoadConfigurationFromFile(string fileName)
        {

        }
    }
}
